﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Net;

namespace Pavilion.Communications
{
    public class ServiceController<T> where T : ITransferringService
    {
        public T GameService { get; private set; }

        private ServiceHost host;
        private Type implementedContract;
        private int port;

        public ServiceController(T gameService, Type implementedContract, int port)
        {
            this.port = port;
            this.implementedContract = implementedContract;
            this.GameService = gameService;
            host = new ServiceHost(gameService);
        }

        public void Connect()
        {
            try
            {
                IPAddress ipAddress = GetLocalIP();
                string urlService = "net.tcp://" + ipAddress.ToString() + ":" + port + "/Pavilion";

                NetTcpBinding tcpBinding = new NetTcpBinding();
                tcpBinding.TransactionFlow = false;
                tcpBinding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
                tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
                tcpBinding.Security.Mode = SecurityMode.None; // <- Very crucial
                tcpBinding.MaxBufferSize = 2147483647;
                tcpBinding.MaxReceivedMessageSize = 2147483647;
                tcpBinding.MaxBufferPoolSize = 2147483647;
                tcpBinding.ReaderQuotas.MaxArrayLength = 2147483647;

                host.AddServiceEndpoint(implementedContract, tcpBinding, urlService);

                ServiceMetadataBehavior metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (metadataBehavior == null)
                {
                    metadataBehavior = new ServiceMetadataBehavior();
                    metadataBehavior.HttpGetUrl = new Uri("http://" + ipAddress.ToString() + ":" + (port + 1) + "/Pavilion");
                    metadataBehavior.HttpGetEnabled = true;
                    metadataBehavior.ToString();
                    host.Description.Behaviors.Add(metadataBehavior);
                    //string urlMeta = metadataBehavior.HttpGetUrl.ToString();
                }

                host.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
                host.Open();
            }
            catch (Exception ex1)
            {
                Console.WriteLine(ex1.StackTrace);
            }
        }

        public void Disconnect()
        {
            try
            {
                host.Close();
            }
            catch { }
        }

        private IPAddress GetLocalIP()
        {
            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());

            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    return ip;
            }

            return null;
        }
    }
}
